package cn.chanel.mall.service.impl;

import cn.chanel.mall.admin.form.GoodsForm;
import cn.chanel.mall.admin.form.GoodsUpdateForm;
import cn.chanel.mall.constant.PrefixUrl;
import cn.chanel.mall.entity.Goods;
import cn.chanel.mall.enums.ResultEnum;
import cn.chanel.mall.exception.MallException;
import cn.chanel.mall.repository.GoodsRepository;
import cn.chanel.mall.service.CategoryService;
import cn.chanel.mall.service.GoodsService;
import cn.chanel.mall.utils.KeyUtil;
import cn.chanel.mall.vo.GoodsVO;
import cn.chanel.mall.vo.ProductListVO;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class GoodsServiceImpl implements GoodsService {
    @Resource
    private GoodsRepository goodsRepository;

    @Resource
    private CategoryService categoryService;

    @Override
    public ProductListVO getAllGoods(int column) {
        if(column < 1){
            throw new MallException(ResultEnum.PARAM_ERROR);
        }
        val allGoods = goodsRepository.findAll();
        return getProductListVO(column, allGoods);
    }

    @Override
    public ProductListVO getAllGoodsByCategory(int column, String category) {
        if(column < 1){
            throw new MallException(ResultEnum.PARAM_ERROR);
        }
        val allGoods = goodsRepository.findAllByCategory(category);
        return getProductListVO(column, allGoods);
    }

    @Override
    public List<GoodsVO> getAllGoods() {
        List<GoodsVO> goodsVOList = new ArrayList<>();
        goodsRepository.findAll().forEach(e -> goodsVOList.add(convert(e)));
        return goodsVOList;
    }

    @Override
    public List<GoodsVO> getAllGoodsByKey(String key) {
        List<GoodsVO> goodsVOList = new ArrayList<>();
        goodsRepository.findAllByNameContains(key).forEach(e -> goodsVOList.add(convert(e)));
        return goodsVOList;
    }

    @Override
    public List<GoodsVO> getAllGoodsByCategory(String category) {
        List<GoodsVO> goodsVOList = new ArrayList<>();
        goodsRepository.findAllByCategory(category).forEach(e -> goodsVOList.add(convert(e)));
        return goodsVOList;
    }

    @Override
    public List<GoodsVO> getAllGoodsByCategoryAndKey(String category, String key) {
        List<GoodsVO> goodsVOList = new ArrayList<>();
        goodsRepository.findAllByCategoryAndNameContains(category, key).forEach(e -> goodsVOList.add(convert(e)));
        return goodsVOList;
    }

    @Override
    public void addNewGoods(String imageFileName, GoodsForm goodsForm) {
        var goods = new Goods();
        goods.setId(KeyUtil.genUniqueKey());
        goods.setName(goodsForm.getName());
        goods.setScore(goodsForm.getScore());
        goods.setPrice(goodsForm.getPrice());
        goods.setDescribe(goodsForm.getDescribe());
        goods.setCategory(goodsForm.getCategory());
        // 根据实际情况的不同去设置
        goods.setImage(PrefixUrl.PREFIX_URL + imageFileName);
        goodsRepository.save(goods);
    }

    @Override
    public GoodsVO getGoodsById(String id) {
        if(StringUtils.hasText(id)){
            var goodsOpt = goodsRepository.findById(id);
            if(goodsOpt.isPresent()){
                return convert(goodsOpt.get());
            }
        }
        throw new MallException(ResultEnum.PARAM_ERROR);
    }

    @Override
    public void updateGoods(String imageFileName, GoodsUpdateForm goodsForm) {
        var goodsId = goodsForm.getId();
        var goodsOpt = goodsRepository.findById(goodsId);
        if(goodsOpt.isEmpty()){
            throw new MallException(ResultEnum.GOODS_INF_ERROR);
        }
        val goods = goodsOpt.get();
        goods.setCategory(goodsForm.getCategory());
        goods.setStock(goodsForm.getStock());
        goods.setDescribe(goodsForm.getDescribe());
        goods.setName(goodsForm.getName());
        goods.setPrice(goodsForm.getPrice());
        goods.setScore(goodsForm.getScore());
        if (imageFileName != null) {
            goods.setImage(PrefixUrl.PREFIX_URL + imageFileName);
        }
        Goods save = goodsRepository.save(goods);
        log.info("Update save success, ret = " + save);
    }

    private ProductListVO getProductListVO(int column, List<Goods> allGoods) {
        var retListVO = new ProductListVO();
        retListVO.setColumn(column);
        var row = allGoods.size() / column;
        var extNum = allGoods.size() % column;
        retListVO.setRow(row + (extNum == 0 ? 0: 1));
        var goodsVOS = new GoodsVO[row][column];
        int cursor = 0;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < column; j++) {
                if(cursor < allGoods.size()){
                    goodsVOS[i][j] = convert(allGoods.get(cursor));
                }
            }
        }
        retListVO.setGoodsVOS(goodsVOS);
        return retListVO;
    }

    private GoodsVO convert(Goods goods) {
        final var goodsVO = new GoodsVO();
        BeanUtils.copyProperties(goods, goodsVO);
        goodsVO.setCategoryEntity(categoryService.getCategoryById(goods.getCategory()));
        return goodsVO;
    }
}
